/*
 *      Author: Honrun
 */
#include "CH58x_common.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesTime.h"
#include "DevicesKey.h"


KeyType g_typeKey;


void vKeyInit(void)
{
    /* configure key pin as input */
    GPIOB_ModeCfg(KEY_HOME_Pin, GPIO_ModeIN_PU);

    g_typeKey.uiKeyValueGet = uiKeyValueGet;
}

/*
Return Value:   按键组合序号（头文件里有定义）
Parameters:     void
Description:    读取当前按键状态
*/
uint32_t uiKeyValueGet(void)
{
    uint32_t Key = KEY_ALL;
    uint8_t i = 0;

    for(i = 0; i < 8; ++i)
    {
        if(RESET != GPIOB_ReadPortPin(KEY_HOME_Pin))
            Key &= ~KEY_HOME;
    }

    return Key;
}

/*
 * Return:      按键状态
 * Parameters:  Value_new:新按键键值; Value_old:旧按键键值;
 * Description: 按键状态获取
 */
static KeyStateEnum enumKeyStateGet(uint32_t uiNew, uint32_t uiOld)
{
    if(uiNew == uiOld)                      /* 当前按键值与上次按键值相同 */
        return keyEqual;
    else if((uiNew & uiOld) == uiOld)       /* 当前按键值在上次按键值基础上增加了新按键 */
        return keyAdd;
    else if((uiNew | uiOld) == uiOld)       /* 当前按键值在上次按键值基础上减少了旧按键 */
        return keyDel;
    else
        return keyAddAndDel;
}

/*
 * Return:      KeyStateEnum：按键状态机的状态
 * Parameters:  ptypeKeyMachine: 按键结构消息
 * Description: 按键状态获取
 */
KeyStateEnum enumKeyMachine(KeyType *ptypeKey)
{
    uint32_t uiKeyNew;
    uint16_t usTimeNow = lTimebaseGet() / 1000, usTimeDelta;

    if((ptypeKey == NULL) || (ptypeKey->uiKeyValueGet == NULL))
        return keyNormal;

    if((uiKeyNew = ptypeKey->uiKeyValueGet()) & 0x8000)
        return keyNormal;

    /* 记录时间、键值变化 */
    switch(enumKeyStateGet(uiKeyNew, ptypeKey->valueLast))
    {
        /* 记录按键按下时间、变化总键值 */
        case keyAdd:
        case keyAddAndDel:
            ptypeKey->valueDown = uiKeyNew;
            ptypeKey->timeDown  = usTimeNow;
            ptypeKey->state     = keyAdd;
            ptypeKey->valueLast = uiKeyNew;
            ptypeKey->cntCombo += (ptypeKey->valueDown == ptypeKey->valueUp);
            break;

        /* 记录按键松开时间、变化总键值 */
        case keyDel:
            ptypeKey->valueUp  |= ptypeKey->valueLast & (~uiKeyNew);
            ptypeKey->timeUp    = usTimeNow;
            ptypeKey->state    |= keyDel;
            ptypeKey->valueLast = uiKeyNew;
            break;

        default: break;
    }

    /* 按键状态转换 */
    switch((uint32_t)ptypeKey->state)
    {
        case keyAdd:
            usTimeDelta = (KEY_SHORT_TIME * ptypeKey->cntCombo) > 500 ? 500 : (KEY_SHORT_TIME * ptypeKey->cntCombo);
            if((usTimeNow - ptypeKey->timeDown) >= usTimeDelta)
            {
                ptypeKey->state = keyShort;
                return ptypeKey->state;
            }
            break;

        case keyShort:
            if((usTimeNow - ptypeKey->timeDown) >= KEY_LONG_TIME)
            {
                ptypeKey->state = keyLong;
                return ptypeKey->state;
            }
            break;

        case keyLong:
            if((usTimeNow - ptypeKey->timeDown) >= KEY_CONTINUE_TIME)
            {
                ptypeKey->state = keyContinuous;
            }
            break;

        case keyContinuous:
            if((usTimeNow - ptypeKey->timeDown) >= KEY_CONTINUE_INTERVAL_TIME)
            {
                ptypeKey->timeDown = usTimeNow;
                return ptypeKey->state;
            }
            break;

        case keyDel | keyAdd:
        case keyDel | keyShort:
        case keyDel | keyLong:
        case keyDel | keyContinuous:
            usTimeDelta = (KEY_SHORT_TIME * ptypeKey->cntCombo) > 500 ? 500 : (KEY_SHORT_TIME * ptypeKey->cntCombo);
            if(((usTimeNow - ptypeKey->timeUp) >= usTimeDelta) && (uiKeyNew == 0))
            {
                ptypeKey->state  = (ptypeKey->state & 0xFF00) | keyUp;
                return ptypeKey->state;
            }
            break;

        default : ptypeKey->cntCombo = 1; ptypeKey->valueUp = 0; break;
    }

    return keyNormal;
}
